package de.clue.corpus.twitter.validate;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;

import org.apache.commons.io.FileUtils;

import de.clue.corpus.twitter.TwitterCorpusConstants;



public class Validator {
	
	private static String[] XML_SCHEMA = { "<tweet>", "<author>", "</author>",
		"<nickname>", "</nickname>", "<time>", "</time>", "<text>",
		"</text>", "<place>", "</place>", "<geoLocation>",
		"</geoLocation>", "<mcount>", "</mcount>", "</tweet>" };
	private final String path;

	
	
	
	public Validator(String path) throws Exception{
		this.path = path;
		
		 validateArguments();
		
	}
	
	private void validateArguments() {
		
		
		if(path == null){
			throw new IllegalArgumentException("path must not be empty!");
		}
		
		File toCheck = new File(path);
		if(!toCheck.exists()){
			throw new IllegalArgumentException("path must exist!");
		}
		
		
	}
	
	public void process(){
		validateFilesInDirectory();
		
	}


	private void validateFilesInDirectory(){
		
		File sourceDirectory = new File(path);
		String[] list = sourceDirectory.list();
		
		String outputPath = createValidDirectory();
		
		for (int i = 0; i < list.length; i++) {
			try {
				String currentFileName = list[i];
				File currentFile = new File(path,currentFileName);
				if(currentFile.isFile()){
					System.out.println("Processing file: " + currentFile.getAbsolutePath());
					testFile(currentFile, outputPath);
					System.out.println("File validated!");
					
				}
			} catch (Exception e) {
				e.printStackTrace();
				
			}
			
		}
		
	}
	
	
	private String createValidDirectory() {
		String validDirectoryPath = path;
		
		try {
			File validDirectory = new File(path + "valid");
			if(!validDirectory.exists()){
				if(validDirectory.mkdirs()){
					validDirectoryPath = validDirectory.getAbsolutePath();
				}
			} else {
				validDirectoryPath = validDirectory.getAbsolutePath();
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return validDirectoryPath;
		
	}

	private void testFile(File file, String outputPath){
		
		DataInputStream in = null;
		Writer out = null;
		boolean startroot = false;
		boolean endroot = false;
		
		try {
			boolean header = false;
			FileInputStream fstream = new FileInputStream(file);

			in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF8")); // Als UTF8 einlesen
			out = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(outputPath + System.getProperty("file.separator") + file.getName()), "UTF8"));
			String lastLine;
			String thisLine = br.readLine();
			System.out.println("Prove!");
			while (thisLine != null) {

				lastLine = thisLine;
				thisLine = br.readLine();

				if (lastLine
						.equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")) {
					header = true;
					out.write(lastLine);
					out.write("\n");
				}
				if (lastLine.equals("<root>")) {
					if (!header) {
						out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
						out.write("\n");
					}
					startroot = true;
					out.write(lastLine);
					out.write("\n");
				} else {
					out.write("<root>");
					out.write("\n");
					startroot = true;
				}
				while (thisLine != null) {
					lastLine = thisLine;
					thisLine = br.readLine();
					if (thisLine == null) {
						if (lastLine.equals("</root>")) {
							out.write(lastLine);
							out.write("\n");
							endroot = true;
						} else {
							lastLine = testLine(lastLine);
							if (lastLine != null) {
								out.write(lastLine);
								out.write("\n");
								out.write("</root>");
								out.write("\n");
								endroot = true;
							} else {
								out.write("</root>");
								out.write("\n");
								endroot = true;
							}
						}
					} else {
						lastLine = testLine(lastLine);
						if (lastLine != null) {
							out.write(lastLine);
							out.write("\n");
						}
					}
				}
			}
			
		} catch (Exception e) {
			System.err.println("Error: " + e.getMessage());
		} finally {
			if(in != null){
				try {
					in.close();
				} catch (Exception e2) {
					// do nothing
				}
			}
			if(out != null){
				try {
					out.flush();
					out.close();
				} catch (Exception e2) {
					// do nothing
				}
			}
		}
		
	}
	
	private String testLine(String line) {
		int x = 0;
		boolean valid = false;

		line = line.replaceAll("<br>", "<br/>"); // Ersetzen durch leeres Element
		line = deleteControllCharacters(line);

		int end = line.length();
		for (int i = 0; i < end; i++) {
			if (line.charAt(i) == '<') {
				int j = i;
				while (line.charAt(j) != '>') {
					j++;
				}
				if (!line.substring(i, j + 1).equals(XML_SCHEMA[x]) && !line.substring(i, j + 1).equals("<br/>")) { // nur wenn nicht <br/>
					return null;
				}
				if(!line.substring(i, j + 1).equals("<br/>")){ // nur wenn nicht <br/>
					x++;
					
				}
			}
		}
			
		return line;
	}
	
	
	private String brRemoval(String wrong) {
		if (wrong == null) {
			return "";
		}
		wrong = wrong.replaceAll("<br>", "<br/>");
		return wrong;
	}

	private String deleteControllCharacters(String delcont) {

		if (delcont == null) {
			return "";
		}
		for (int i = 0; i < 32; i++) {
			char c = (char) i;
			delcont = removeChar(delcont, c);
		}
		char c = (char) 127;
		delcont = removeChar(delcont, c);
		return delcont;
	}

	private String removeChar(String s, char c) {
		StringBuffer r = new StringBuffer();
		// r.setLength( s.length() ); ERZEUT die NullCharacter im Buffer!
		int current = 0;
		for (int i = 0; i < s.length(); i++) {
			char cur = s.charAt(i);
			if (cur != c) {
				r.append(cur);
			} else {
				r.append(" ");
			}
		}
		return r.toString();
	}

}
